package com.mvvm.start.common.utils

import android.text.TextUtils
import com.mvvm.start.base.BaseApplication
import com.mvvm.start.base.utils.loge
import com.mvvm.start.common.api.DownApi
import com.mvvm.start.common.network.RetrofitHelp
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch
import okhttp3.ResponseBody
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import java.io.*
import java.util.*


/**
 * @author
 * @功能: Retrofit下载文件工具类
 * @Creat 2/24/21 10:24 AM
 * @Compony 465008238@qq.com
 */
object DownloadUtils {
    private var mAppPath = ""

    //这个路径在应用程序内部 应用卸载时会自动删除
    private val DOWN_PATH_TO_APP =
        BaseApplication.context.getExternalFilesDir(null).toString() + File.separator + "Download" +
                File.separator

    /**
     * @param url 下载路径
     * @param path 存储位置
     * @param start 开始回调
     * @param progress 下载进度回调
     * @param finish 完成下载回调
     * @param failure 下载错误回调
     */
    fun downloadFile(
        url: String,
        fileName: String,
        start: () -> Unit,
        progress: (Int) -> Unit,
        finish: (String) -> Unit,
        failure: (String) -> Unit
    ) {
        "downloadFile".loge("UpDateAppHelper")
        //通过Url得到保存到本地的文件名
        if (FileUtils.createOrExistsDir(DOWN_PATH_TO_APP)) {
            mAppPath = DOWN_PATH_TO_APP + fileName
        }
        if (TextUtils.isEmpty(mAppPath)) {
            failure("存储路径错误")
            return
        }
        /**
         * 如果有新的app下载说明 新版app尚未下载那就清楚下载文件夹 清除历史下载的App版本
         */
        FileUtils.delAllFile(File(DOWN_PATH_TO_APP))
        RetrofitHelp.creat(DownApi::class.java).downloadFile(url)
            .enqueue(object : Callback<ResponseBody?> {
                override fun onResponse(
                    call: Call<ResponseBody?>,
                    response: Response<ResponseBody?>
                ) {
                    "RetrofitHelp onResponse ".loge()
                    MainScope().launch(Dispatchers.IO) {
                        writeFileDisk(response, File(mAppPath), start, progress, finish, failure)
                    }
                }

                override fun onFailure(call: Call<ResponseBody?>, t: Throwable) {
                    t.message?.let { failure(it) }
                }
            })
    }


    private fun writeFileDisk(
        response: Response<ResponseBody?>,
        file: File,
        start: () -> Unit,
        progress: (Int) -> Unit,
        finish: (String) -> Unit,
        failure: (String) -> Unit
    ) {
        "writeFileDisk ".loge()
        start()
        var currentLength: Long = 0
        var os: OutputStream? = null
        if (response.body() == null) {
            failure("资源错误！")
            return
        }
        val inputstream = response.body()!!.byteStream()
        val totalLength = response.body()!!.contentLength()
        try {
            os = FileOutputStream(file)
            var len: Int
            val buff = ByteArray(1024)
            while (inputstream.read(buff).also { len = it } != -1) {
                os.write(buff, 0, len)
                currentLength += len.toLong()
                progress((100 * currentLength / totalLength).toInt())
                if (currentLength == totalLength) {
                    finish(mAppPath)
                }
            }
        } catch (e: FileNotFoundException) {
            failure("未找到文件！")
            e.printStackTrace()
        } catch (e: IOException) {
            failure("IO错误！")
            e.printStackTrace()
        } finally {
            if (os != null) {
                try {
                    os.close()
                } catch (e: IOException) {
                    e.printStackTrace()
                }
            }
            if (inputstream != null) {
                try {
                    inputstream.close()
                } catch (e: IOException) {
                    e.printStackTrace()
                }
            }
        }
    }
}